use reqwest::header::{HeaderMap, HeaderValue};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;

use super::super::my_err::MyErr;
use super::super::util_file;

/// 身份证数据
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct IdCard {
    pub face_or_back: usize, //  1：正面，2：反面

    // 正面
    pub name: Option<String>,       //	姓名。
    pub sex: Option<String>,        //	性别。
    pub ethnicity: Option<String>,  //	民族。
    pub birth_date: Option<String>, //	出生日期。
    pub address: Option<String>,    //	住址。
    pub id_number: Option<String>,  //	身份证号码。

    // 背面
    pub issue_authority: Option<String>, //	签发机关。(背面)
    pub valid_period: Option<String>,    //	有效期限。(背面)
    pub valid_from_date: Option<String>, //	有效期起始日期。(背面)
    pub valid_to_date: Option<String>,   //	有效期结束日期。(背面)
}

/// 营业执照数据
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct BusinessLicense {
    pub credit_code: Option<String>,        //	统一社会信用代码。
    pub company_name: Option<String>,       //  营业名称。
    pub company_type: Option<String>,       //  类型。
    pub business_address: Option<String>,   //  营业场所/住所。
    pub legal_person: Option<String>,       //  法人/负责人。
    pub business_scope: Option<String>,     //  经营范围。
    pub registered_capital: Option<String>, //	注册资本。
    pub registration_date: Option<String>,  //	注册日期。
    pub valid_period: Option<String>,       //	营业期限。
    pub valid_from_date: Option<String>,    //	格式化营业期限起始日期。
    pub valid_to_date: Option<String>,      //	格式化营业期限终止日期。
    pub company_form: Option<String>,       //	组成形式。
    pub issue_date: Option<String>,         //	发照日期。
    pub title: Option<String>,              //	证照标题。
}

/// 驾驶证数据
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct DriverLicense {
    pub face_or_back: usize, //  1：正面，2：反面

    // 正面
    pub license_number: Option<String>,     //	证号。
    pub name: Option<String>,               //	姓名。
    pub sex: Option<String>,                //	性别。
    pub nationality: Option<String>,        //	国籍。
    pub address: Option<String>,            //	住址。
    pub birth_date: Option<String>,         //	出生日期。
    pub initial_issue_date: Option<String>, //	初次领证日期。
    pub approved_type: Option<String>,      //	准驾类型。
    pub issue_authority: Option<String>,    //	发证单位。
    pub valid_from_date: Option<String>,    //	有效起始日期。
    pub valid_to_date: Option<String>,      //	有效期结束日期。
    pub valid_period: Option<String>,       //	有效期限。

    // 背面
    pub record_number: Option<String>, //档案编号。
    pub record: Option<String>,        //记录。
}

/// 行驶证数据
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct VehicleLicense {
    pub face_or_back: usize, //  1：正面，2：反面

    // 正面
    pub address: Option<String>,              //住址。
    pub engine_number: Option<String>,        //发动机号码。
    pub issue_date: Option<String>,           //发证日期。
    pub model: Option<String>,                //品牌型号。
    pub owner: Option<String>,                //所有人。
    pub license_plate_number: Option<String>, //号牌号码。
    pub registration_date: Option<String>,    //注册日期。
    pub use_nature: Option<String>,           //使用性质。
    pub vehicle_type: Option<String>,         //车辆类型。
    pub vin_code: Option<String>,             //车辆识别代码。
    pub issue_authority: Option<String>,      //签发机关。

    // 背面
    pub inspection_record: Option<String>,  //检验记录。
    pub passenger_capacity: Option<String>, //核定载人数。
    pub total_weight: Option<String>,       //总质量。
    pub curb_weight: Option<String>,        //整备质量。
    pub permitted_weight: Option<String>,   //核定载质量。
    pub overall_dimension: Option<String>,  //外廓尺寸。
    pub traction_weight: Option<String>,    //准牵引总质量。
    pub energy_sign: Option<String>,        //能源标志。
    pub record_number: Option<String>,      //档案编号。
    pub remarks: Option<String>,            //备注。
    pub barcode_number: Option<String>,     //条形码编号。
}

/// 银行卡数据
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct BankCard {
    pub card_type: Option<String>, //卡种（CC（贷记卡），SCC（准贷记卡），DCC（存贷合一卡），DC（储蓄卡），PC（预付卡））。
    pub bank_name: Option<String>, //银行名称。
    pub card_number: Option<String>, //银行卡号。
    pub valid_to_date: Option<String>, //有效期限。
}

impl super::Aliyun {
    /// 通过身份证URL地址，读取身份证文字信息
    /// url 图片url地址
    ///
    /// ```
    /// let aliyun : crate::mylib::aliyun::Aliyun = crate::mylib::aliyun::Aliyun::new_config();
    ///
    /// let url =  "http://fleet.tc1680.cn/attr/img/2024-10-03/idcard.jpg";
    ///
    /// let _ = aliyun.read_idcard_info_by_url(url).await;
    /// ```
    #[allow(dead_code)]
    pub async fn read_idcard_info_by_url(&self, url: &str) -> Result<IdCard, MyErr> {
        let method = reqwest::Method::GET;
        let content_type = super::CONTENT_TYPE_URL;
        let canonical_uri = "/";
        let host = "ocr-api.cn-hangzhou.aliyuncs.com";
        let x_acs_action = "RecognizeIdcard";
        let x_acs_version = "2021-07-07";

        // 数据头
        let mut headers = HeaderMap::new();
        headers.insert("x-acs-action", HeaderValue::from_static(x_acs_action));
        headers.insert("x-acs-version", HeaderValue::from_static(x_acs_version));
        headers.insert("host", HeaderValue::from_static(host));
        headers.insert("content-type", HeaderValue::from_static(content_type));

        // url参数
        let mut query_param: HashMap<String, String> = HashMap::new();
        query_param.insert("Url".to_string(), url.to_string());

        let body_string = "".to_string();
        let body_json: serde_json::Map<String, Value> = serde_json::Map::new();
        let body_binary: Vec<u8> = Vec::new();

        let res_json = self
            .request_payload(
                method,
                canonical_uri,
                &mut headers,
                query_param,
                body_string,
                body_json,
                body_binary,
            )
            .await?;

        println!("\n\n {:?} \n\n", res_json);

        if res_json.get("Data").is_some() {
            value_to_idcard(res_json)
        } else {
            let code = res_json.get("Code").and_then(Value::as_str).unwrap_or_default();
            let message = res_json.get("Message").and_then(Value::as_str).unwrap_or_default();

            Err(MyErr::Msg(format!("错误:{},详情:{}", code, message)))
        }
    }

    /// 通过图片路径，读取身份证文字信息
    /// file_path 图片路径
    ///
    /// ```
    /// let aliyun : crate::mylib::aliyun::Aliyun = crate::mylib::aliyun::Aliyun::new_config();
    ///
    /// let file_path =  "/home/laobu/Documents/身份证.jpg";
    ///
    /// let _ = aliyun.read_idcard_info_by_file(file_path).await;
    /// ```
    #[allow(dead_code)]
    pub async fn read_idcard_info_by_file(&self, file_path: &str) -> Result<IdCard, MyErr> {
        let method = reqwest::Method::POST;
        let content_type = super::CONTENT_TYPE_STREAM;
        let canonical_uri = "/";
        let host = "ocr-api.cn-hangzhou.aliyuncs.com";
        let x_acs_action = "RecognizeIdcard";
        let x_acs_version = "2021-07-07";

        // 数据头
        let mut headers = HeaderMap::new();
        headers.insert("x-acs-action", HeaderValue::from_static(x_acs_action));
        headers.insert("x-acs-version", HeaderValue::from_static(x_acs_version));
        headers.insert("host", HeaderValue::from_static(host));
        headers.insert("content-type", HeaderValue::from_static(content_type));

        // url参数
        let query_param: HashMap<String, String> = HashMap::new();

        let body_string = "".to_string();
        let body_json: serde_json::Map<String, Value> = serde_json::Map::new();
        let body_binary: Vec<u8> = util_file::read_file_binary(file_path)?;

        let res_json = self
            .request_payload(
                method,
                canonical_uri,
                &mut headers,
                query_param,
                body_string,
                body_json,
                body_binary,
            )
            .await?;

        println!("\n\n {:?} \n\n", res_json);

        if res_json.get("Data").is_some() {
            value_to_idcard(res_json)
        } else {
            let code = res_json.get("Code").and_then(Value::as_str).unwrap_or_default();
            let message = res_json.get("Message").and_then(Value::as_str).unwrap_or_default();

            Err(MyErr::Msg(format!("错误:{},详情:{}", code, message)))
        }
    }

    /// 通过URL地址 读取营业执照文字信息
    /// url 图片url地址
    ///
    /// ```
    /// let aliyun : crate::mylib::aliyun::Aliyun = crate::mylib::aliyun::Aliyun::new_config();
    ///
    /// let url =  "http://fleet.tc1680.cn/attr/img/2024-10-03/business.jpg";
    ///
    /// let _ = aliyun.read_business_by_url(url).await;
    /// ```
    #[allow(dead_code)]
    pub async fn read_business_by_url(&self, url: &str) -> Result<BusinessLicense, MyErr> {
        let method = reqwest::Method::GET;
        let content_type = super::CONTENT_TYPE_URL;
        let canonical_uri = "/";
        let host = "ocr-api.cn-hangzhou.aliyuncs.com";
        let x_acs_action = "RecognizeBusinessLicense";
        let x_acs_version = "2021-07-07";

        // 数据头
        let mut headers = HeaderMap::new();
        headers.insert("x-acs-action", HeaderValue::from_static(x_acs_action));
        headers.insert("x-acs-version", HeaderValue::from_static(x_acs_version));
        headers.insert("host", HeaderValue::from_static(host));
        headers.insert("content-type", HeaderValue::from_static(content_type));

        // url参数
        let mut query_param: HashMap<String, String> = HashMap::new();
        query_param.insert("Url".to_string(), url.to_string());

        let body_string = "".to_string();
        let body_json: serde_json::Map<String, Value> = serde_json::Map::new();
        let body_binary: Vec<u8> = Vec::new();

        let res_json = self
            .request_payload(
                method,
                canonical_uri,
                &mut headers,
                query_param,
                body_string,
                body_json,
                body_binary,
            )
            .await?;

        println!("\n\n {:?} \n\n", res_json);

        if res_json.get("Data").is_some() {
            value_to_business_license(res_json)
        } else {
            let code = res_json.get("Code").and_then(Value::as_str).unwrap_or_default();
            let message = res_json.get("Message").and_then(Value::as_str).unwrap_or_default();

            Err(MyErr::Msg(format!("错误:{},详情:{}", code, message)))
        }
    }

    /// 通过营业执照图片地址，读取营业执照文字信息
    /// file_path 图片路径
    ///
    /// ```
    /// let aliyun : crate::mylib::aliyun::Aliyun = crate::mylib::aliyun::Aliyun::new_config();
    ///
    /// let file_path =  "/home/laobu/Documents/营业执照.jpg";
    ///
    /// let _ = aliyun.read_business_info_by_file(file_path).await;
    /// ```
    #[allow(dead_code)]
    pub async fn read_business_info_by_file(&self, file_path: &str) -> Result<BusinessLicense, MyErr> {
        let method = reqwest::Method::POST;
        let content_type = super::CONTENT_TYPE_STREAM;
        let canonical_uri = "/";
        let host = "ocr-api.cn-hangzhou.aliyuncs.com";
        let x_acs_action = "RecognizeBusinessLicense";
        let x_acs_version = "2021-07-07";

        // 数据头
        let mut headers = HeaderMap::new();
        headers.insert("x-acs-action", HeaderValue::from_static(x_acs_action));
        headers.insert("x-acs-version", HeaderValue::from_static(x_acs_version));
        headers.insert("host", HeaderValue::from_static(host));
        headers.insert("content-type", HeaderValue::from_static(content_type));

        // url参数
        let query_param: HashMap<String, String> = HashMap::new();

        let body_string = "".to_string();
        let body_json: serde_json::Map<String, Value> = serde_json::Map::new();
        let body_binary: Vec<u8> = util_file::read_file_binary(file_path)?;

        let res_json = self
            .request_payload(
                method,
                canonical_uri,
                &mut headers,
                query_param,
                body_string,
                body_json,
                body_binary,
            )
            .await?;

        println!("\n\n {:?} \n\n", res_json);

        if res_json.get("Data").is_some() {
            value_to_business_license(res_json)
        } else {
            let code = res_json.get("Code").and_then(Value::as_str).unwrap_or_default();
            let message = res_json.get("Message").and_then(Value::as_str).unwrap_or_default();

            Err(MyErr::Msg(format!("错误:{},详情:{}", code, message)))
        }
    }

    /// 通过驾驶证图片地址，读取驾驶证文字信息
    /// file_path 图片路径
    ///
    /// ```
    /// let aliyun : crate::mylib::aliyun::Aliyun = crate::mylib::aliyun::Aliyun::new_config();
    ///
    /// let file_path =  "/home/laobu/Documents/驾驶证.jpg";
    ///
    /// let _ = aliyun.read_driver_license_info_by_file(file_path).await;
    /// ```
    #[allow(dead_code)]
    pub async fn read_driver_license_info_by_file(&self, file_path: &str) -> Result<DriverLicense, MyErr> {
        let method = reqwest::Method::POST;
        let content_type = super::CONTENT_TYPE_STREAM;
        let canonical_uri = "/";
        let host = "ocr-api.cn-hangzhou.aliyuncs.com";
        let x_acs_action = "RecognizeDrivingLicense";
        let x_acs_version = "2021-07-07";

        // 数据头
        let mut headers = HeaderMap::new();
        headers.insert("x-acs-action", HeaderValue::from_static(x_acs_action));
        headers.insert("x-acs-version", HeaderValue::from_static(x_acs_version));
        headers.insert("host", HeaderValue::from_static(host));
        headers.insert("content-type", HeaderValue::from_static(content_type));

        // url参数
        let query_param: HashMap<String, String> = HashMap::new();

        let body_string = "".to_string();
        let body_json: serde_json::Map<String, Value> = serde_json::Map::new();
        let body_binary: Vec<u8> = util_file::read_file_binary(file_path)?;

        let res_json = self
            .request_payload(
                method,
                canonical_uri,
                &mut headers,
                query_param,
                body_string,
                body_json,
                body_binary,
            )
            .await?;

        println!("\n\n {:?} \n\n", res_json);

        if res_json.get("Data").is_some() {
            value_to_driver_license(res_json)
        } else {
            let code = res_json.get("Code").and_then(Value::as_str).unwrap_or_default();
            let message = res_json.get("Message").and_then(Value::as_str).unwrap_or_default();

            Err(MyErr::Msg(format!("错误:{},详情:{}", code, message)))
        }
    }

    /// 通过行驶证图片地址，读取行驶证文字信息
    /// file_path 图片路径
    ///
    /// ```
    /// let aliyun : crate::mylib::aliyun::Aliyun = crate::mylib::aliyun::Aliyun::new_config();
    ///
    /// let file_path =  "/home/laobu/Documents/行驶证.jpg";
    ///
    /// let _ = aliyun.read_vehicle_license_info_by_file(file_path).await;
    /// ```
    #[allow(dead_code)]
    pub async fn read_vehicle_license_info_by_file(&self, file_path: &str) -> Result<VehicleLicense, MyErr> {
        let method = reqwest::Method::POST;
        let content_type = super::CONTENT_TYPE_STREAM;
        let canonical_uri = "/";
        let host = "ocr-api.cn-hangzhou.aliyuncs.com";
        let x_acs_action = "RecognizeVehicleLicense";
        let x_acs_version = "2021-07-07";

        // 数据头
        let mut headers = HeaderMap::new();
        headers.insert("x-acs-action", HeaderValue::from_static(x_acs_action));
        headers.insert("x-acs-version", HeaderValue::from_static(x_acs_version));
        headers.insert("host", HeaderValue::from_static(host));
        headers.insert("content-type", HeaderValue::from_static(content_type));

        // url参数
        let query_param: HashMap<String, String> = HashMap::new();

        let body_string = "".to_string();
        let body_json: serde_json::Map<String, Value> = serde_json::Map::new();
        let body_binary: Vec<u8> = util_file::read_file_binary(file_path)?;

        let res_json = self
            .request_payload(
                method,
                canonical_uri,
                &mut headers,
                query_param,
                body_string,
                body_json,
                body_binary,
            )
            .await?;

        println!("\n\n {:?} \n\n", res_json);

        if res_json.get("Data").is_some() {
            value_to_vehicle_license(res_json)
        } else {
            let code = res_json.get("Code").and_then(Value::as_str).unwrap_or_default();
            let message = res_json.get("Message").and_then(Value::as_str).unwrap_or_default();

            Err(MyErr::Msg(format!("错误:{},详情:{}", code, message)))
        }
    }

    /// 通过银行卡图片地址，读取银行卡文字信息
    /// file_path 图片路径
    ///
    /// ```
    /// let aliyun : crate::mylib::aliyun::Aliyun = crate::mylib::aliyun::Aliyun::new_config();
    ///
    /// let file_path =  "/home/laobu/Documents/银行卡.jpg";
    ///
    /// let _ = aliyun.read_bank_card_info_by_file(file_path).await;
    /// ```
    #[allow(dead_code)]
    pub async fn read_bank_card_info_by_file(&self, file_path: &str) -> Result<BankCard, MyErr> {
        let method = reqwest::Method::POST;
        let content_type = super::CONTENT_TYPE_STREAM;
        let canonical_uri = "/";
        let host = "ocr-api.cn-hangzhou.aliyuncs.com";
        let x_acs_action = "RecognizeBankCard";
        let x_acs_version = "2021-07-07";

        // 数据头
        let mut headers = HeaderMap::new();
        headers.insert("x-acs-action", HeaderValue::from_static(x_acs_action));
        headers.insert("x-acs-version", HeaderValue::from_static(x_acs_version));
        headers.insert("host", HeaderValue::from_static(host));
        headers.insert("content-type", HeaderValue::from_static(content_type));

        // url参数
        let query_param: HashMap<String, String> = HashMap::new();

        let body_string = "".to_string();
        let body_json: serde_json::Map<String, Value> = serde_json::Map::new();
        let body_binary: Vec<u8> = util_file::read_file_binary(file_path)?;

        let res_json = self
            .request_payload(
                method,
                canonical_uri,
                &mut headers,
                query_param,
                body_string,
                body_json,
                body_binary,
            )
            .await?;

        println!("\n\n {:?} \n\n", res_json);

        if res_json.get("Data").is_some() {
            value_to_bank_card(res_json)
        } else {
            let code = res_json.get("Code").and_then(Value::as_str).unwrap_or_default();
            let message = res_json.get("Message").and_then(Value::as_str).unwrap_or_default();

            Err(MyErr::Msg(format!("错误:{},详情:{}", code, message)))
        }
    }
}

// 把阿里云返回的[身份证数据]转为 struct
fn value_to_idcard(res_json: Value) -> Result<IdCard, MyErr> {
    let mut bean = IdCard::default();

    println!("\n\n\n data:{:?} \n\n\n", res_json);

    if let Some(root_str) = res_json.get("Data").and_then(Value::as_str) {
        let root = serde_json::from_str::<Value>(root_str)?;
        if let Some(data) = root.get("data").and_then(Value::as_object) {
            if let Some(face) = data.get("face").and_then(Value::as_object) {
                if let Some(face_data) = face.get("data").and_then(Value::as_object) {
                    bean.face_or_back = 1; // 1：正面，2：背面

                    let name = face_data.get("name").and_then(Value::as_str).unwrap_or_default();
                    let sex = face_data.get("sex").and_then(Value::as_str).unwrap_or_default();
                    let ethnicity = face_data.get("ethnicity").and_then(Value::as_str).unwrap_or_default();
                    let birth_date = face_data.get("birthDate").and_then(Value::as_str).unwrap_or_default();
                    let address = face_data.get("address").and_then(Value::as_str).unwrap_or_default();
                    let id_number = face_data.get("idNumber").and_then(Value::as_str).unwrap_or_default();

                    bean.name = Some(name.to_string());
                    bean.sex = Some(sex.to_string());
                    bean.ethnicity = Some(ethnicity.to_string());
                    bean.birth_date = Some(date_format(birth_date));
                    bean.address = Some(address.to_string());
                    bean.id_number = Some(id_number.to_string());

                    Ok(bean)
                } else {
                    Err(MyErr::Msg("无法解析身份证OCR数据:3".to_string()))
                }
            } else if let Some(back) = data.get("back").and_then(Value::as_object) {
                if let Some(back_data) = back.get("data").and_then(Value::as_object) {
                    bean.face_or_back = 2; // 1：正面，2：背面

                    let issue_authority = back_data.get("issueAuthority").and_then(Value::as_str).unwrap_or_default();
                    let valid_period = back_data.get("validPeriod").and_then(Value::as_str).unwrap_or_default();

                    bean.issue_authority = Some(issue_authority.to_string());
                    bean.valid_period = Some(date_format(valid_period));

                    let (s, e) = valid_format(valid_period);
                    bean.valid_from_date = Some(s);
                    bean.valid_to_date = Some(e);

                    Ok(bean)
                } else {
                    Err(MyErr::Msg("无法解析身份证OCR数据:3".to_string()))
                }
            } else {
                Err(MyErr::Msg("无法解析身份证OCR数据:2".to_string()))
            }
        } else {
            Err(MyErr::Msg("无法解析身份证OCR数据:1".to_string()))
        }
    } else {
        Err(MyErr::Msg("无法解析身份证OCR数据:0".to_string()))
    }
}

// 把阿里云返回的[营业执照数据]转为 struct
fn value_to_business_license(res_json: Value) -> Result<BusinessLicense, MyErr> {
    let mut bean = BusinessLicense::default();

    println!("\n\n\n data:{:?} \n\n\n", res_json);

    if let Some(root_str) = res_json.get("Data").and_then(Value::as_str) {
        let root = serde_json::from_str::<Value>(root_str)?;
        if let Some(data) = root.get("data").and_then(Value::as_object) {
            let credit_code = data.get("creditCode").and_then(Value::as_str).unwrap_or_default();
            let company_name = data.get("companyName").and_then(Value::as_str).unwrap_or_default();
            let company_type = data.get("companyType").and_then(Value::as_str).unwrap_or_default();
            let business_address = data.get("businessAddress").and_then(Value::as_str).unwrap_or_default();
            let legal_person = data.get("legalPerson").and_then(Value::as_str).unwrap_or_default();
            let business_scope = data.get("businessScope").and_then(Value::as_str).unwrap_or_default();
            let registered_capital = data.get("registeredCapital").and_then(Value::as_str).unwrap_or_default();
            let registration_date = data.get("RegistrationDate").and_then(Value::as_str).unwrap_or_default();
            let valid_period = data.get("validPeriod").and_then(Value::as_str).unwrap_or_default();
            let valid_from_date = data.get("validFromDate").and_then(Value::as_str).unwrap_or_default();
            let valid_to_date = data.get("validToDate").and_then(Value::as_str).unwrap_or_default();
            let company_form = data.get("companyForm").and_then(Value::as_str).unwrap_or_default();
            let issue_date = data.get("issueDate").and_then(Value::as_str).unwrap_or_default();
            let title = data.get("title").and_then(Value::as_str).unwrap_or_default();

            bean.credit_code = Some(credit_code.to_string());
            bean.company_name = Some(company_name.to_string());
            bean.company_type = Some(company_type.to_string());
            bean.business_address = Some(business_address.to_string());
            bean.legal_person = Some(legal_person.to_string());
            bean.business_scope = Some(business_scope.to_string());
            bean.registered_capital = Some(registered_capital.to_string());
            bean.registration_date = Some(date_format(registration_date));
            bean.valid_period = Some(valid_period.to_string());
            bean.valid_from_date = Some(valid_format2(valid_from_date));
            bean.valid_to_date = Some(valid_format2(valid_to_date));
            bean.company_form = Some(company_form.to_string());
            bean.issue_date = Some(date_format(issue_date));
            bean.title = Some(title.to_string());

            Ok(bean)
        } else {
            Err(MyErr::Msg("无法解析营业执照OCR数据:1".to_string()))
        }
    } else {
        Err(MyErr::Msg("无法解析营业执照OCR数据:0".to_string()))
    }
}

// 把阿里云返回的[驾驶证数据]转为 struct
fn value_to_driver_license(res_json: Value) -> Result<DriverLicense, MyErr> {
    let mut bean = DriverLicense::default();

    println!("\n\n\n data:{:?} \n\n\n", res_json);

    if let Some(root_str) = res_json.get("Data").and_then(Value::as_str) {
        let root = serde_json::from_str::<Value>(root_str)?;
        if let Some(data) = root.get("data").and_then(Value::as_object) {
            if let Some(face) = data.get("face").and_then(Value::as_object) {
                if let Some(face_data) = face.get("data").and_then(Value::as_object) {
                    bean.face_or_back = 1; // 1：正面，2：背面

                    bean.license_number = face_data.get("licenseNumber").and_then(Value::as_str).map(|v| v.to_owned()); // 证号。
                    bean.name = face_data.get("name").and_then(Value::as_str).map(|v| v.to_owned()); // 姓名。
                    bean.sex = face_data.get("sex").and_then(Value::as_str).map(|v| v.to_owned()); // 性别。
                    bean.nationality = face_data.get("nationality").and_then(Value::as_str).map(|v| v.to_owned()); // 国籍。
                    bean.address = face_data.get("address").and_then(Value::as_str).map(|v| v.to_owned()); // 住址。
                    bean.birth_date = face_data.get("birthDate").and_then(Value::as_str).map(|v| v.to_owned()); // 出生日期。
                    bean.initial_issue_date = face_data.get("initialIssueDate").and_then(Value::as_str).map(|v| v.to_owned()); // 初次领证日期。
                    bean.approved_type = face_data.get("approvedType").and_then(Value::as_str).map(|v| v.to_owned()); // 准驾类型。
                    bean.issue_authority = face_data.get("issueAuthority").and_then(Value::as_str).map(|v| v.to_owned()); // 发证单位。
                    bean.valid_from_date = face_data.get("validFromDate").and_then(Value::as_str).map(|v| v.to_owned()); // 有效起始日期。

                    let valid_period = face_data.get("validPeriod").and_then(Value::as_str).unwrap_or_default(); // 有效期限。  

                    let (_, e) = valid_format3(valid_period);
                    bean.valid_to_date = Some(e);
                    bean.valid_period = Some(valid_period.to_string());

                    Ok(bean)
                } else {
                    Err(MyErr::Msg("无法解析驾驶证OCR数据:3".to_string()))
                }
            } else if let Some(back) = data.get("back").and_then(Value::as_object) {
                if let Some(back_data) = back.get("data").and_then(Value::as_object) {
                    bean.face_or_back = 2; // 1：正面，2：背面

                    bean.license_number = back_data.get("licenseNumber").and_then(Value::as_str).map(|v| v.to_owned()); // 证号。
                    bean.name = back_data.get("name").and_then(Value::as_str).map(|v| v.to_owned()); // 姓名。
                    bean.record_number = back_data.get("recordNumber").and_then(Value::as_str).map(|v| v.to_owned()); // 档案编号。
                    bean.record = back_data.get("record").and_then(Value::as_str).map(|v| v.to_owned()); // 记录。

                    Ok(bean)
                } else {
                    Err(MyErr::Msg("无法解析驾驶证OCR数据:3".to_string()))
                }
            } else {
                Err(MyErr::Msg("无法解析驾驶证OCR数据:2".to_string()))
            }
        } else {
            Err(MyErr::Msg("无法解析驾驶证OCR数据:1".to_string()))
        }
    } else {
        Err(MyErr::Msg("无法解析驾驶证OCR数据:0".to_string()))
    }
}

// 把阿里云返回的[行驶证数据]转为 struct
fn value_to_vehicle_license(res_json: Value) -> Result<VehicleLicense, MyErr> {
    let mut bean = VehicleLicense::default();

    println!("\n\n\n data:{:?} \n\n\n", res_json);

    if let Some(root_str) = res_json.get("Data").and_then(Value::as_str) {
        let root = serde_json::from_str::<Value>(root_str)?;
        if let Some(data) = root.get("data").and_then(Value::as_object) {
            if let Some(face) = data.get("face").and_then(Value::as_object) {
                if let Some(face_data) = face.get("data").and_then(Value::as_object) {
                    bean.face_or_back = 1; // 1：正面，2：背面

                    bean.address = face_data.get("address").and_then(Value::as_str).map(|v| v.to_owned()); //住址。
                    bean.engine_number = face_data.get("engineNumber").and_then(Value::as_str).map(|v| v.to_owned()); //发动机号码。
                    bean.issue_date = face_data.get("issueDate").and_then(Value::as_str).map(|v| v.to_owned()); //发证日期。
                    bean.model = face_data.get("model").and_then(Value::as_str).map(|v| v.to_owned()); //品牌型号。
                    bean.owner = face_data.get("owner").and_then(Value::as_str).map(|v| v.to_owned()); //所有人。
                    bean.license_plate_number = face_data.get("licensePlateNumber").and_then(Value::as_str).map(|v| v.to_owned()); //号牌号码。
                    bean.registration_date = face_data.get("registrationDate").and_then(Value::as_str).map(|v| v.to_owned()); //注册日期。
                    bean.use_nature = face_data.get("useNature").and_then(Value::as_str).map(|v| v.to_owned()); //使用性质。
                    bean.vehicle_type = face_data.get("vehicleType").and_then(Value::as_str).map(|v| v.to_owned()); //车辆类型。
                    bean.vin_code = face_data.get("vinCode").and_then(Value::as_str).map(|v| v.to_owned()); //车辆识别代码。
                    bean.issue_authority = face_data.get("issueAuthority").and_then(Value::as_str).map(|v| v.to_owned()); //签发机关。

                    Ok(bean)
                } else {
                    Err(MyErr::Msg("无法解析行驶证OCR数据:3".to_string()))
                }
            } else if let Some(back) = data.get("back").and_then(Value::as_object) {
                if let Some(back_data) = back.get("data").and_then(Value::as_object) {
                    bean.face_or_back = 2; // 1：正面，2：背面

                    bean.license_plate_number = back_data.get("licensePlateNumber").and_then(Value::as_str).map(|v| v.to_owned()); //号牌号码。
                    bean.inspection_record = back_data.get("inspectionRecord").and_then(Value::as_str).map(|v| v.to_owned()); //检验记录。
                    bean.passenger_capacity = back_data.get("passengerCapacity").and_then(Value::as_str).map(|v| v.to_owned()); //核定载人数。
                    bean.total_weight = back_data.get("totalWeight").and_then(Value::as_str).map(|v| v.to_owned()); //总质量。
                    bean.curb_weight = back_data.get("curbWeight").and_then(Value::as_str).map(|v| v.to_owned()); //整备质量。
                    bean.permitted_weight = back_data.get("permittedWeight").and_then(Value::as_str).map(|v| v.to_owned()); //核定载质量。
                    bean.overall_dimension = back_data.get("overallDimension").and_then(Value::as_str).map(|v| v.to_owned()); //外廓尺寸。
                    bean.traction_weight = back_data.get("tractionWeight").and_then(Value::as_str).map(|v| v.to_owned()); //准牵引总质量。
                    bean.energy_sign = back_data.get("energySign").and_then(Value::as_str).map(|v| v.to_owned()); //能源标志。
                    bean.record_number = back_data.get("recordNumber").and_then(Value::as_str).map(|v| v.to_owned()); //档案编号。
                    bean.remarks = back_data.get("remarks").and_then(Value::as_str).map(|v| v.to_owned()); //备注。
                    bean.barcode_number = back_data.get("barcodeNumber").and_then(Value::as_str).map(|v| v.to_owned()); //条形码编号。

                    Ok(bean)
                } else {
                    Err(MyErr::Msg("无法解析行驶证OCR数据:3".to_string()))
                }
            } else {
                Err(MyErr::Msg("无法解析行驶证OCR数据:2".to_string()))
            }
        } else {
            Err(MyErr::Msg("无法解析驾行驶OCR数据:1".to_string()))
        }
    } else {
        Err(MyErr::Msg("无法解析驾行驶OCR数据:0".to_string()))
    }
}

// 把阿里云返回的[银行卡数据]转为 struct
fn value_to_bank_card(res_json: Value) -> Result<BankCard, MyErr> {
    let mut bean = BankCard::default(); 

    println!("\n\n\n data:{:?} \n\n\n", res_json);

    if let Some(root_str) = res_json.get("Data").and_then(Value::as_str) {
        let root = serde_json::from_str::<Value>(root_str)?;
        if let Some(data) = root.get("data").and_then(Value::as_object) {
            bean.card_type = data.get("cardType").and_then(Value::as_str).map(|v| v.to_owned()); //卡种（CC（贷记卡），SCC（准贷记卡），DCC（存贷合一卡），DC（储蓄卡），PC（预付卡））。
            bean.bank_name = data.get("bankName").and_then(Value::as_str).map(|v| v.to_owned()); //银行名称。
            bean.card_number = data.get("cardNumber").and_then(Value::as_str).map(|v| v.to_owned()); //银行卡号。
            bean.valid_to_date = data.get("validToDate").and_then(Value::as_str).map(|v| v.to_owned()); //有效期限。 

            Ok(bean)
        } else {
            Err(MyErr::Msg("无法解析银行卡OCR数据:1".to_string()))
        }
    } else {
        Err(MyErr::Msg("无法解析银行卡OCR数据:0".to_string()))
    }
}

/// 格式化时间把 2021年2月9日 转为 2021-02-09
fn date_format(date_str: &str) -> String {
    let strs: Vec<&str> = date_str.split(&['年', '月', '日'][..]).filter(|v| !v.is_empty()).collect();
    if strs.len() == 3 {
        let year = strs[0].parse::<i32>().unwrap_or_default();
        let month = strs[1].parse::<i32>().unwrap_or_default();
        let day = strs[2].parse::<i32>().unwrap_or_default();

        if year > 1970 && year < 2999 && month > 0 && month < 13 && day > 0 && day < 32 {
            return format!("{}-{:02}-{:02}", year, month, day);
        } else {
            date_str.to_string()
        }
    } else {
        date_str.to_string()
    }
}

/// 格式化有效期：把 2021.2.9 - 2039.12.3 转为起始日期（2021-02-09）和结束日期（2039-12-03）
fn valid_format(valid_str: &str) -> (String, String) {
    let days: Vec<&str> = valid_str.split(&['-'][..]).map(|v| v.trim()).filter(|v| !v.is_empty()).collect();

    if days.len() == 2 {
        let sday = crate::mylib::util_date::str_to_day(days[0]);
        let eday = crate::mylib::util_date::str_to_day(days[1]);
        (sday, eday)
    } else {
        ("".to_string(), "".to_string())
    }
}

/// 格式化有效期：把 2021.2.9 - 2039.12.3 转为起始日期（2021-02-09）和结束日期（2039-12-03）
fn valid_format2(valid_str: &str) -> String {
    if valid_str.len() == 8 {
        let y = &valid_str[0..4];
        let m = &valid_str[4..6];
        let d = &valid_str[6..8];
        return format!("{}-{}-{}", y, m, d);
    } else {
        "".to_string()
    }
}

/// 格式化有效期：把 "2024-04-24至2034-04-24" 转为起始日期（2024-04-24）和结束日期（2034-04-24）
fn valid_format3(valid_str: &str) -> (String, String) {
    let days: Vec<&str> = valid_str.split(&['至'][..]).map(|v| v.trim()).filter(|v| !v.is_empty()).collect();

    if days.len() == 2 {
        let sday = crate::mylib::util_date::str_to_day(days[0]);
        let eday = crate::mylib::util_date::str_to_day(days[1]);
        (sday, eday)
    } else {
        ("".to_string(), "".to_string())
    }
}
